//==========================================================================
//            Draws 2D using hardware acceleration without slow GDI calls.
//==========================================================================
#ifndef __D3D11PAD_H
#define __D3D11PAD_H

#include "Resources.h"

extern oapi::Font *def_Font;
extern oapi::Pen *def_Pen;

class Texture;
class TextureMgr;
class Scene;

inline void D3DXCOLORSWAP(D3DXCOLOR *x) {
    float a = x->r;
    x->r = x->b;
    x->b = a;
}

class D3D11Pad : public oapi::Sketchpad
{
public:
    static void GlobalInit();
    static void GlobalExit();

    D3D11Pad(D3D11Config *pConfig,
    		 Scene *pScene,
             SURFHANDLE surf,
             TextureMgr * textureMgr,
             bool _static = false );
    virtual ~D3D11Pad();

    oapi::Font *SetFont( oapi::Font *font ) const;
    oapi::Pen *SetPen( oapi::Pen *pen ) const;
    oapi::Brush *SetBrush( oapi::Brush *brush ) const;

    void SetTextAlign( TAlign_horizontal TA_h = LEFT, TAlign_vertical TA_v = TOP );

    DWORD SetTextColor( DWORD color );
    DWORD SetBackgroundColor( DWORD color );
    void SetBackgroundMode( BkgMode bk_mode );

    DWORD GetCharSize();
    DWORD GetTextWidth( const char *str, int len = 0 );

    void SetOrigin( int x, int y );
    bool Text( int x, int y, const char *str, int len );
    void Pixel( int x, int y, DWORD color );
    void MoveTo( int x, int y );
    void LineTo( int x, int y );
    void Line( int x0, int y0, int x1, int y1 );
    void Rectangle( int x0, int y0, int x1, int y1 );
    void Ellipse( int x0, int y0, int x1, int y1 );
    void Polygon( const oapi::IVECTOR2 *pt, int npt );
    void Polyline( const oapi::IVECTOR2 *pt, int npt );
    HDC GetDC();
private:
    HDC hDC;

    TextureMgr * m_textureMgr;

    bool HasPen();
    bool HasBrush();
    bool HasWidePen();
    bool IsDashed();

    void Ellipse2( float x, float y, float w, float h );
    void Rectangle2( float x, float y, float w, float h );
    void Rectangle3( float x, float y, float w, float h, int width );
    void Lines( D3DXVECTOR3 *pVert, int count );

    int CheckTriangle( short x, const D3DXVECTOR3 *pt, const WORD *Idx, float hd, short npt, bool bSharp );
    int CreatePolyIndexList( const D3DXVECTOR3 *pt, short npt, WORD *Out );

    mutable oapi::Font *cfont;
    mutable oapi::Pen *cpen;
    mutable oapi::Brush *cbrush;

    mutable D3DXCOLOR
        TextColor,
        PenColor,
        BrushColor,
        BkColor;

    DWORD
        BkMode,
        HAlign, VAlign;

    int    origx, origy, cx, cy;

    DWORD
        width,
        height;
    Texture *TEX;
    ID3D11Texture2D *Tex;
//    ID3D11ShaderResourceView *SRV_Tex;        //?
    ID3D11RenderTargetView *RTV_Tex;        //?

    void ExtendVertexBuffer( UINT new_size );
    void ExtendIndexBuffer( UINT new_size );
    void SetRParams( D3DXVECTOR4 *data = NULL );

    static UINT
        vb_size,
        ib_size;

    static ID3D11InputLayout
        *IL_D3DXVECTOR3;

    static ID3D11Buffer
        *Circle_low,
        *Circle_high,
        *VB,
        *IB,
        *cb_VS,
        *cb_PS;


    static ID3D11VertexShader
        *VS_Ellipse,
        *VS_WideRect,
        *VS_Line,
        *VS_Fill;

    static ID3D11PixelShader
        *PS_Draw,
        *PS_Fill;

    static const UINT
        SkpStride,
        VBOffset;

    static const float    BlendFactors[4];

    struct cbuffer0 {
        D3DXMATRIX M;
        D3DXVECTOR4 Data;
    } VSCB;

    struct cbuffer1 {
        D3DXCOLOR COL;
        UINT32 Dash;
        float nodata[3];
    } PSCB;
};

class D3D11PadFont : public oapi::Font
{
    friend class GDIPad;
    friend class D3D11Pad;
public:
    D3D11PadFont( int height, bool prop, const char *face, Style style, int orientation );
    virtual ~D3D11PadFont();

private:
    class D3D11Text *pFont;
    HFONT hFont;
    bool bDelete;
    float rotation;
};

class D3D11PadPen : public oapi::Pen
{
    friend class GDIPad;
    friend class D3D11Pad;
public:
    //tech init ?
    D3D11PadPen( int style, int width, DWORD col );
    virtual ~D3D11PadPen();
private:
    int style, width;
    D3DXCOLOR fcolor;
    HPEN hPen;
};

class D3D11PadBrush : public oapi::Brush
{
    friend class GDIPad;
    friend class D3D11Pad;
public:
    D3D11PadBrush( DWORD col );
    virtual ~D3D11PadBrush();
private:
    D3DXCOLOR fcolor;
    HBRUSH hBrush;
};

//====================================================================
//====================================================================

typedef struct {
    float x, y;
    float tu, tv;
} TEXTVERTEX;

struct D3D11FontData {
    float w, h;        // X,Y position of the charter baseline
    float sp;
    float tx0, ty0;
    float tx1, ty1;
    BYTE s, e;        // s=special charter flag, e=extend charter height
};

class D3D11Text {
public:
    static void GlobalInit();
    static void GlobalExit();

    D3D11Text();
    virtual ~D3D11Text();

    void SetCharSet( int _CharSet = ANSI_CHARSET );    // Must be set before Init

    bool Init( HFONT hFont, int final = 255 );
    bool Init( LOGFONTA *fnt, int final = 255 );
    bool Init( int size = 24, int Style = FIXED_PITCH | FF_MODERN, int weight = 500, int last = 255 );
    bool Init( int size = 24, char *fontname = NULL, int weight = 500, int last = 255 );

    void SetLineSpace( int percent = 10 );
    void SetTextSpace( int space = 0 );        // Percent of average width (default=0)
    void SetTextShare( int percent = 0 );    // Percent of average width (default=0)

    void SetColor( DWORD c );                // 0xAARRGGBB
    void SetColor( float _red, float _green, float _blue, float _alpha = 1.0f );
    void SetRotation( float deg );

    void Reset();
    float Width();
    int GetLineSpace();

    float Length( const char *format, ... );
    float Length2( const char *str, int le = -1 );
    float Length( char c );

    void SetTextHAlign( int x ); // 0-left, 1=center, 2=right
    void SetTextVAlign( int x ); // 0-top, 1=base, 2=bottom
    float Print( D3DXCOLOR *color, int x, int y, const char *str, int len = -1, D3DXMATRIX *pVP = NULL, D3DXCOLOR *bbox = NULL );

    void GetD3D11TextMetrics( TEXTMETRICA *t ) {    memcpy( t, &tm, sizeof(TEXTMETRICA) );    }
private:
    char *Buffer;

    float red, green, blue, alpha;

    int tex_w, tex_h, sharing, spacing, linespacing;
    float
        max,            // If several strings are printed. This is the wide of the widest one
        rotation;
    int last, CharSet, HAlign, VAlign;

    ID3D11Texture2D *Tex;
    IDXGISurface1 *Surf;
    ID3D11ShaderResourceView *SRV;

    D3D11FontData *Data;
    _ABC *Abc;
    TEXTMETRICA tm;

    static ID3D11InputLayout *IL_TextVertex;
    static ID3D11Buffer
        *VB,
        *IB,
        *cb_COLOR;
    static ID3D11VertexShader *VS_Fill_Font;
    static ID3D11PixelShader *PS_Fill, *PS_Font;
};

//====================================================================
//====================================================================
//2D label
class Labels {
public:
    Labels();
    ~Labels();
};

#endif
